﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.ServiceModel;
using KPIS.GERP.Models;
using KPIS.GERP.Models.Class;
using KPIS.GERP.Models.SYS;
using System.Data.Entity;

namespace KPIS.GERP.WCF.SYS
{
    [ServiceContract]
    public interface IGerpAuthenService
    {

        #region Add to monitoring

        [OperationContract]
        List<UserLoginMonitor> GetMonitor();

        [OperationContract]
        void AddOrUpdateMonitor(int userId, string clientIp, string systemId, string userCode, string fullName, int? posId, string currentStatus, string icon = null);

        #endregion


        #region Audit

        [OperationContract]
        void Login(int userId, string clientIp, string systemId, string userCode, string fullName, int? posId);

        [OperationContract]
        bool Active(int userId, string clientIp, string systemId, string currentStatus, string icon);

        [OperationContract]
        bool Logout(int userId, string clientIp, string systemId);

        [OperationContract]
        List<ServerStartUp> GetServerStartup();

        #endregion


        #region OneTimeData Service

        [OperationContract]
        string CreateOTP(int EmpId,
                         string RedirectUrl);

        [OperationContract]
        string CreateOTP2(int EmpId,
                          string RedirectUrl,
                          string customField1,
                          string customField2,
                          string customField3);

        [OperationContract]
        OTP GetOTP(string key);

        [OperationContract]
        OTP GetAndDestroyOTP(string key);

        #endregion


        #region Old

        //[OperationContract]
        //Dictionary<string, string> GetSessionInfo(Guid key, string ipAddress);

        //[OperationContract]
        //void DoActivity(Guid key, string ipAddress);

        //[OperationContract]
        //void Logout(Guid key, string ipAddress);

        //[OperationContract]
        //IEnumerable<UserLoginMonitor> GetUserLoginMonitor();

        //[OperationContract]
        //void DoActivityAnonymous(string ipAddress);

        //[OperationContract]
        //string KeepUserTempInfo(string userName, string usercode, int userSeq, int empSeq, int workingJobSiteSeq, string workingJobSiteName, int workAreaSeq, int height, string secret, int expireInMinute);

        //[OperationContract]
        //Dictionary<string, string> GetUserTempInfo(string tokenKey);

        //[OperationContract]
        //User GetWebUserTempInfo(string tokenKey, out UserTempInfo userTempInfo);

        //[OperationContract]
        //void DestroyUserTempInfo(string tokenKey);

        #endregion old
    }

    /// <summary>
    /// This is for sharing data login between module by using database, not use cookie
    /// </summary>
    [ServiceErrorBehavior(typeof (ElmahErrorHandler))]
    [System.ServiceModel.Activation.AspNetCompatibilityRequirements(
        RequirementsMode = System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)]
    public class GerpAuthenService : IGerpAuthenService
    {
        public List<UserLoginMonitor> GetMonitor()
        {
            using (var db = new GERPContext(true))
            {
                return db.UserLoginMonitors.ToList();
            }
        }

        public void AddOrUpdateMonitor(int userId, string clientIp, string systemId, string userCode, string fullName, int? posId, string currentStatus, string icon = null)
        {
            using (var db = new GERPContext(false))
            {
                var loginMonitor = db.UserLoginMonitors.FirstOrDefault(o => o.UserId == userId && o.ClientIp == clientIp && o.SystemId == systemId);

                if (loginMonitor != null)
                {
                    loginMonitor.Update(userCode, fullName, posId, currentStatus, icon);
                    db.Entry(loginMonitor).State = EntityState.Modified;
                    db.SaveChanges();
                }
                else
                {
                    loginMonitor = new UserLoginMonitor();
                    loginMonitor.Initial(userId, clientIp, systemId, userCode, fullName, posId, currentStatus, icon);
                    db.UserLoginMonitors.Add(loginMonitor);
                    db.SaveChanges();
                }
            }
        }

        public bool Active(int userId, string clientIp, string systemId, string currentStatus, string icon)
        {
            try
            {
                using (var db = new GERPContext(false))
                {
                    // Logout old
                    var monitor = db.UserLoginMonitors.FirstOrDefault(o => o.UserId == userId && o.ClientIp == clientIp && o.SystemId == systemId);

                    if (monitor != null)
                    {
                        monitor.Update(currentStatus, icon);
                        db.Entry(monitor).State = EntityState.Modified;
                        db.SaveChanges();
                        return true;

                    }
                    else
                    {
                        return false; // Not found monitor, forgot to add monitor ???
                    }

                }
            }
            catch
            {
                return false;
            }
        }

        public void Login(int userId, string clientIp, string systemId, string userCode, string fullName, int? posId)
        {
            using (var db = new GERPContext(true))
            {
                try
                {
                    // checkOldAvailble
                    UserLoginLogout unloggedEntrys = db.UserLoginLogouts.FirstOrDefault(o => o.LogoutDateTime == null && o.UserId == userId
                                                                                             && o.ClientIp == clientIp && o.SystemId == systemId);

                    if (unloggedEntrys == null) // Add new 
                    {
                        UserLoginLogout newUserLoginLogout = new UserLoginLogout(userId, clientIp, systemId, userCode, fullName, posId);
                        db.UserLoginLogouts.Add(newUserLoginLogout);
                    }
                    else
                    {
                        unloggedEntrys.Login(userId, clientIp, systemId, userCode, fullName, posId);
                    }
                    //  Found 1 error on 1/May/2014
                } catch(Exception ex)
                {
                    var error = ex;
                }
                db.SaveChanges();
            }
        }

        public bool Logout(int userId, string clientIp, string systemId)
        {
            using (var db = new GERPContext(true))
            {
                // checkOldAvailble
                UserLoginLogout unloggedEntrys = db.UserLoginLogouts.FirstOrDefault(o => o.LogoutDateTime == null && o.UserId == userId
                                                                                         && o.ClientIp == clientIp && o.SystemId == systemId);

                if (unloggedEntrys != null) // Add new 
                {
                    unloggedEntrys.Logout();
                    db.SaveChanges();
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        public List<ServerStartUp> GetServerStartup()
        {
            using (var db = new GERPContext(false))
            {
                return db.ServerStartUps.ToList();
            }
        }

        public string CreateOTP(int EmpId,
                         string RedirectUrl)
        {
            using (var db = new GERPContext(true))
            {
                var employee = db.Employees.FirstOrDefault(o => o.EmpId == EmpId && o.RecordStatus != "D");
                var user = db.Users.FirstOrDefault(o => o.EmpId == EmpId && o.RecordStatus != "D");
                if(employee == null || user == null)
                {
                    return null;
                }

                var newOtd = new OTP
                    {
                        EmpId = EmpId,
                        EmployeeFullName = employee.FullName,
                        UserId = user.UserId,
                        UserCode = user.Code,
                        WorkingJobSiteSeq = employee.WorkingJobSiteId,
                        WorkingJobSiteName = employee.JobSite != null ? employee.JobSite.Name : string.Empty,
                        WorkAreaId = employee.JobSite != null ? employee.JobSite.WorkAreaId : null,
                        RedirectUrl = RedirectUrl,
                        CustomField1 = null,
                        CustomField2 = null,
                        CustomField3 = null
                    };
                db.Otps.Add(newOtd);
                db.SaveChanges();
                return newOtd.UniqueId.ToString();
            }
        }

        public string CreateOTP2(int EmpId,
                                string redirectUrl,
                                string CustomField1 = null,
                                string CustomField2 = null,
                                string CustomField3 = null)
        {
            using (var db = new GERPContext(true))
            {
                var employee = db.Employees.FirstOrDefault(o => o.EmpId == EmpId && o.RecordStatus != "D");
                var user = db.Users.FirstOrDefault(o => o.EmpId == EmpId && o.RecordStatus != "D");
                if(employee == null || user == null)
                {
                    return null;
                }
                var newOtd = new OTP
                    {
                        EmpId = EmpId,
                        EmployeeFullName = employee.FullName,
                        UserId = user.UserId,
                        UserCode = user.Code,
                        WorkingJobSiteSeq = employee.WorkingJobSiteId,
                        WorkingJobSiteName = employee.JobSite != null ? employee.JobSite.Name : string.Empty,
                        WorkAreaId = employee.JobSite != null ? employee.JobSite.WorkAreaId : null,
                        RedirectUrl = redirectUrl,
                        CustomField1 = CustomField1,
                        CustomField2 = CustomField2,
                        CustomField3 = CustomField3
                    };
                db.Otps.Add(newOtd);
                db.SaveChanges();
                return newOtd.UniqueId.ToString();
            }
        }

        public OTP GetOTP(string key)
        {
            if(string.IsNullOrWhiteSpace(key)) return null;

            using (var db = new GERPContext(false))
            {
                var resultOtd = db.Otps.FirstOrDefault(o => o.UniqueId == new Guid(key));
                return resultOtd;
            }
        }

        public OTP GetAndDestroyOTP(string key)
        {
            using (var db = new GERPContext(false))
            {
                var resultOtd = db.Otps.FirstOrDefault(o => o.UniqueId == new Guid(key));
                db.Otps.Remove(resultOtd);
                return resultOtd;
            }
        }

        //public Guid Authenticate(string userseq, string empseq, string username, string workingjobsiteseq, string workingjobsitename, string workareaseq, string height, string secret, string ipAddress)
        //{
        //	var key = AddMonitor( userseq,  empseq,  username,  workingjobsiteseq,  workingjobsitename,  workareaseq,  height,  ipAddress);

        //	UpdateLastLoginIfNotLogout(ipAddress, key);

        //	LogLoginUser(userseq, empseq, username, workingjobsiteseq, workingjobsitename, workareaseq, height, ipAddress, key);

        //	return key;
        //}

        //public Dictionary<string, string> GetSessionInfo(Guid key, string ipAddress)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		var resultList = db.UserLoginMonitors.Where(o => o.Key == key
        //																  && !o.LogoutDateTime.HasValue
        //																  && ipAddress == o.UserIp).ToList();

        //		var result = resultList.FirstOrDefault(o => !o.IsExpire);

        //		if (result != null)
        //		{
        //			result.DoActivity();
        //			db.SaveChanges();
        //			return result.CastSessionDataToArray();
        //		}

        //		return null;
        //	}
        //}

        //public void DoActivity(Guid key, string ipAddress)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		var result = db.UserLoginMonitors.FirstOrDefault(o => o.Key == key
        //															  && ipAddress == o.UserIp
        //															  && !o.LogoutDateTime.HasValue);
        //		if (result == null)
        //		{
        //			Logging.GerpLog.Unknown(string.Format(
        //				"Can't find user monitor with key {0}, ipAddress {1} and logoutdatetime = null);", key, ipAddress));
        //			return;
        //		}

        //		result.DoActivity();
        //		db.SaveChanges();
        //	}
        //}

        //public void DoActivityAnonymous(string ipAddress)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		var result = db.UserLoginMonitors.FirstOrDefault(o => o.Key == Guid.Empty
        //															  && ipAddress == o.UserIp);

        //		if (result != null)
        //		{
        //			result.DoActivity();
        //			db.SaveChanges();
        //		}
        //		else
        //		{
        //			result = new UserLoginMonitor();
        //			result.Login("Annonymous", null, null, null, null, null, null, ipAddress);
        //			result.DoActivity();
        //			db.UserLoginMonitors.Add(result);
        //			db.SaveChanges();
        //		}
        //	}
        //}

        //public string KeepUserTempInfo(string userName, string usercode, int userSeq, int empSeq, int workingJobSiteSeq, string workingJobSiteName, int workAreaSeq, int height, string secret, int expireInMinute)
        //{
        //	using(var db = new GERPContext(false))
        //	{
        //		var firstOrDefault = db.Users.ToList().FirstOrDefault(o => CompareUtility.IsStringsEqual(o.Code, usercode));
        //			var data = new UserTempInfo
        //				{
        //					ExpireOn = DateTime.Now.AddMinutes(expireInMinute),
        //					UserName = userName,
        //					UserSeq = userSeq,
        //					EmpSeq = empSeq,
        //					WorkingJobSiteSeq = workingJobSiteSeq,
        //					WorkingJobSiteName = workingJobSiteName,
        //					WorkAreaSeq = workAreaSeq,
        //					Height = height,
        //					UserId = firstOrDefault != null ? (int?)firstOrDefault.UserId :null,
        //					Secret = secret
        //				};
        //			data.GenerateTokenKey();

        //			db.UserTempInfos.Add(data);
        //			db.SaveChanges();
        //			return data.TokenKey;
        //	}
        //}

        //public Dictionary<string, string> GetUserTempInfo(string tokenKey)
        //{
        //	using(var db = new GERPContext(false))
        //	{
        //		var uti = db.UserTempInfos.FirstOrDefault(o => o.TokenKey == tokenKey);
        //		if (uti == null || uti.IsExpire()) return null;
        //		return new Dictionary<string, string>
        //			{
        //				{"Id", Convert.ToString(uti.Id)},
        //				{"TokenKey", Convert.ToString(uti.TokenKey)},
        //				{"ExpireOn", Convert.ToString(uti.ExpireOn)},
        //				{"UserName", Convert.ToString(uti.UserName)},
        //				{"UserSeq", Convert.ToString(uti.UserSeq)},
        //				{"EmpSeq", Convert.ToString(uti.EmpSeq)},
        //				{"WorkingJobSiteSeq", Convert.ToString(uti.WorkingJobSiteSeq)},
        //				{"WorkingJobSiteName", Convert.ToString(uti.WorkingJobSiteName)},
        //				{"WorkAreaSeq", Convert.ToString(uti.WorkAreaSeq)},
        //				{"Height", Convert.ToString(uti.Height)},
        //				{"Secret", Convert.ToString(uti.Secret)},
        //			};
        //	}
        //}

        //public User GetWebUserTempInfo(string tokenKey, out UserTempInfo userTempInfo)
        //{
        //	using (var db = new GERPContext(false))
        //	{
        //		var uti = db.UserTempInfos.FirstOrDefault(o => o.TokenKey == tokenKey);
        //		userTempInfo = uti;
        //		if (uti == null || uti.IsExpire()) return null;

        //		uti.User = db.Users.FirstOrDefault(o => o.UserId == uti.UserId);

        //		return uti.User;
        //	}
        //}

        //public void DestroyUserTempInfo(string tokenKey)
        //{
        //	using (var db = new GERPContext(false))
        //	{
        //		var uti = db.UserTempInfos.FirstOrDefault(o => o.TokenKey == tokenKey);
        //		if(uti == null) return;
        //		db.UserTempInfos.Remove(uti);
        //		db.SaveChanges();
        //	}
        //}

        //public void Logout(Guid key, string ipAddress)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		var monitor = db.UserLoginMonitors.FirstOrDefault(o => o.Key == key
        //															  && ipAddress == o.UserIp
        //															  && !o.LogoutDateTime.HasValue);
        //		if (monitor == null)
        //		{
        //			Logging.GerpLog.Error("This user is not loggin");
        //		}
        //		else
        //		{
        //			monitor.Logout();
        //		}

        //		// Update Login Logout Audit
        //		var loginlogout = db.UserLoginLogouts.FirstOrDefault(o => o.UserLoginMonitorKey == key);

        //		if (loginlogout != null)
        //		{
        //			loginlogout.Logout();
        //		}

        //		db.SaveChanges();
        //	}
        //}

        //public IEnumerable<UserLoginMonitor> GetUserLoginMonitor()
        //{
        //	using (var db = new GERPContext(false))
        //	{
        //		var loginMonitorList = db.UserLoginMonitors.ToList();

        //		return loginMonitorList;
        //	}
        //}

        //public Guid AddMonitor(string userseq, string empseq, string username, string workingjobsiteseq, string workingjobsitename, string workareaseq, string height, string ipAddress)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		var result = db.UserLoginMonitors.FirstOrDefault(o => o.UserName == username
        //														 && ipAddress == o.UserIp);

        //		if (result != null)
        //		{
        //			result.Login(userseq, empseq, username, workingjobsiteseq, workingjobsitename, workareaseq, height, ipAddress);
        //			result.DoActivity();
        //			db.SaveChanges();
        //		}
        //		else
        //		{
        //			result = new UserLoginMonitor();
        //			result.Login(userseq, empseq, username, workingjobsiteseq, workingjobsitename, workareaseq, height, ipAddress);
        //			result.DoActivity();
        //			db.UserLoginMonitors.Add(result);
        //			db.SaveChanges();
        //		}

        //		return result.Key;
        //	}
        //}

        //public void LogLoginUser(string userseq, string empseq, string username, string workingjobsiteseq, string workingjobsitename, string workareaseq, 
        //	string height, string ipAddress, Guid userLoginMonitorKey)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		var newLoginData = new UserLoginLogout();
        //		newLoginData.UserLoginMonitorKey = userLoginMonitorKey;
        //		newLoginData.UserName = username;
        //		newLoginData.VisitFromIpAddress = ipAddress;
        //		newLoginData.CustomField1 = workingjobsitename;
        //		newLoginData.CustomField2 = userseq;
        //		newLoginData.CustomField3 = empseq;
        //		newLoginData.CustomField4 = workingjobsiteseq;
        //		newLoginData.CustomField5 = workareaseq;
        //		newLoginData.Login();
        //		db.UserLoginLogouts.Add(newLoginData);
        //		db.SaveChanges();
        //	}
        //}

        //public void UpdateLastLoginIfNotLogout(string ipAddress, Guid userLoginMonitorKey)
        //{
        //	using (var db = new GERPContext(true))
        //	{
        //		// Update monitor
        //		var monitor = db.UserLoginMonitors.FirstOrDefault(o => o.Key == userLoginMonitorKey);

        //		if (monitor != null && !monitor.LogoutDateTime.HasValue)
        //			monitor.Logout();

        //		// Update Login Logout Audit
        //		var loginlogout = db.UserLoginLogouts.FirstOrDefault(o => o.UserLoginMonitorKey == userLoginMonitorKey);
        //		if (loginlogout != null)
        //			loginlogout.Logout();

        //		db.SaveChanges();
        //	}
        //}
    }
}